/*
 * FileSystem.h
 *
 *  Created on: 10 jul. 2012
 *      Author: niels
 */

#ifndef FILESYSTEM_H_
#define FILESYSTEM_H_

#include <cstring>

#include "akk/akkInclude.h"
#include "BlockCache.h"
#include "swap.h"

struct block
{
	byte bytes[DBLKSIZ];
	daddr_x address;
    
    template <class T> void readInto(T& t, int& offset)
    {
        memcpy(reinterpret_cast<char*>(&t), &bytes[offset], sizeof(T));
        offset += sizeof(T);
        
        t = swap_endian<T>(t);
    }
    template <class T> void readIntoArray(T* t, int length, int& offset)
    {
        for (int i=0; i<length; ++i)
        {
            readInto<T>(t[i], offset);
        }
    }


};

/**
 * Een Inode object representeert een actieve inode.
 * [Denk aan de AIT].
 */
class Inode
{
    friend class FileSystem;
    int	number;		// het inode nummer
    int	usecount;	// hoe veel referenties zijn er
    dinode ino;

    // ... andere attributen en methodes ...
};

/**
 * Een OpenFile representeert een geopende file.
 * [Denk aan de SOFT].
 */
class	OpenFile
{
    friend class FileSystem;
    Inode  * ip;	// de bijbehorende inode.
    int	     usecount;	// usage counter
    long     iopos;	// de huidige I/O positie

    // ... andere attributen en methodes ...
};

/* Voetnoot:
 * Als in jou opzet een class File bestaat dan is
 * hierboven "File * fp;" ipv "Inode * ip;"
 * misschien netter/beter.
 */


/**
 * Een FileSysteem object is de interne representatie
 * van een gemount filesysteem.
 * Het is tevens de "facade" voor de achterliggende
 * verzameling classes/objecten die de verdere functionaliteit
 * realiseren.
 */
class FileSystem
{
public:

    FileSystem(const char *device);
    ~FileSystem();
    Inode *findInode(const char *absolute_path);
    Inode *findFile(Inode *dirptr, const char *filename);
    void releaseInode(Inode *ip);
    OpenFile *open(const char *path);
    int read(OpenFile *fileptr, char buffer[], int count);
    int lseek(OpenFile *fileptr, long  offset, int whence);
    void close(OpenFile *fileptr);
	block* 	readBlock(daddr_x address);
	void	freeBlock(daddr_x address);
	daddr_x	getFreeBlock();
	long	getFreeSpace();
	dinode	getInode(ino_x number);
	int 	getFreeInode();
	fblk 	getFblk(block* b);
	void 	writeBlock(block* b);
	void 	freeInodeData(dinode inode);
	void 	freeIndirections(daddr_x address, int depth);
	void	freeInode(ino_x number);
	void 	writeToBlock(fblk fblk, block* b);
private:

    filsys filesystem;
    fstream *disk;
    void printSuperBlock();


};

#endif /* FILESYSTEM_H_ */
